﻿/*
 * Created by SharpDevelop.
 * User: issuser
 * Date: 2010-12-22
 * Time: 10:54
 * 
 * To change this template use Tools | Options | Coding | Edit Standard Headers.
 */
using System;
using System.Collections.Generic;
using System.Data.SQLite;
using System.Globalization;

namespace SQLiteFunctions
{

   
    [SQLiteFunction(FuncType = FunctionType.Collation, Name = "UTF8CI")]
    public class IgnoreCaseCollation : SQLiteFunction
    {
        public override int Compare(string x, string y)
        {
            return string.Compare(x, y, StringComparison.InvariantCultureIgnoreCase);
        }
    }

    [SQLiteFunction(FuncType = FunctionType.Scalar, Name = "instr")]
    public class IndexOfFunction : SQLiteFunction
    {
        public override object Invoke(object[] args)
        {
            var str = args[0] as string;
            var findStr = args[1] as string;
            var startIndex = (int)args[2];

            if (args.Length == 3)
                return str.IndexOf(findStr, startIndex);
            else
                return str.IndexOf(findStr, startIndex, (int)args[3]);
        }
    }


    public abstract class DatePartAddFunction : SQLiteFunction
    {
        public override object Invoke(object[] args)
        {
            var date = (DateTime)args[0];
            var value = (int)args[2];
            return OnInvoke(date, value);
        }

        protected abstract object OnInvoke(DateTime date, int value);
    }

    [SQLiteFunction(FuncType = FunctionType.Scalar, Name = "add_year")]
    public class AddYearFunction : DatePartAddFunction
    {
        protected override object OnInvoke(DateTime date, int value)
        {
            return date.AddYears(value);
        }
    }

    [SQLiteFunction(FuncType = FunctionType.Scalar, Name = "add_month")]
    public class AddMonthFunction : DatePartAddFunction
    {
        protected override object OnInvoke(DateTime date, int value)
        {
            return date.AddMonths(value);
        }
    }

    [SQLiteFunction(FuncType = FunctionType.Scalar, Name = "add_day")]
    public class AddDayFunction : DatePartAddFunction
    {
        protected override object OnInvoke(DateTime date, int value)
        {
            return date.AddDays(value);
        }
    }

    [SQLiteFunction(FuncType = FunctionType.Scalar, Name = "add_hour")]
    public class AddHourFunction : DatePartAddFunction
    {
        protected override object OnInvoke(DateTime date, int value)
        {
            return date.AddHours(value);
        }
    }

    [SQLiteFunction(FuncType = FunctionType.Scalar, Name = "add_minute")]
    public class AddMinuteFunction : DatePartAddFunction
    {
        protected override object OnInvoke(DateTime date, int value)
        {
            return date.AddMinutes(value);
        }
    }

    [SQLiteFunction(FuncType = FunctionType.Scalar, Name = "add_second")]
    public class AddSecondFunction : DatePartAddFunction
    {
        protected override object OnInvoke(DateTime date, int value)
        {
            return date.AddSeconds(value);
        }
    }

    [SQLiteFunction(FuncType = FunctionType.Scalar, Name = "diff_date")]
    public class DateDiffFunction : SQLiteFunction
    {
        public override object Invoke(object[] args)
        {
            return ((DateTime)args[0] - (DateTime)args[1]).Ticks;
        }
    }

    [SQLiteFunction(FuncType = FunctionType.Scalar, Name = "trunc")]
    public class TruncateFunction : SQLiteFunction
    {
        public override object Invoke(object[] args)
        {
            var type = Type.GetTypeCode(args[0].GetType());
            if (type == TypeCode.Double)
                return Math.Truncate((double)args[0]);
            else if (type == TypeCode.Decimal)
                return Math.Truncate((Decimal)args[0]);

            decimal value = 0;
            if (decimal.TryParse(args[0].ToString(),out value))
                return Math.Truncate(value);
            throw new ArgumentException();
        }
    }
}